home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / iso2022_cn.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  7.1 KB  |  298 lines

  1.  
  2. /*
  3.  * ISO-2022-CN
  4.  */
  5.  
  6. /* Specification: RFC 1922 */
  7.  
  8. #define ESC 0x1b
  9. #define SO  0x0e
  10. #define SI  0x0f
  11.  
  12. /*
  13.  * The state is composed of one of the following values
  14.  */
  15. #define STATE_ASCII          0
  16. #define STATE_TWOBYTE        1
  17. /*
  18.  * and one of the following values, << 8
  19.  */
  20. #define STATE2_NONE                   0
  21. #define STATE2_DESIGNATED_GB2312      1
  22. #define STATE2_DESIGNATED_CNS11643_1  2
  23. /*
  24.  * and one of the following values, << 16
  25.  */
  26. #define STATE3_NONE                   0
  27. #define STATE3_DESIGNATED_CNS11643_2  1
  28.  
  29. #define SPLIT_STATE \
  30.   unsigned int state1 = state & 0xff, state2 = (state >> 8) & 0xff, state3 = state >> 16
  31. #define COMBINE_STATE \
  32.   state = (state3 << 16) | (state2 << 8) | state1
  33.  
  34. static int
  35. iso2022_cn_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  36. {
  37.   state_t state = conv->istate;
  38.   SPLIT_STATE;
  39.   int count = 0;
  40.   unsigned char c;
  41.   for (;;) {
  42.     c = *s;
  43.     if (c == ESC) {
  44.       if (n < count+4)
  45.         goto none;
  46.       if (s[1] == '$') {
  47.         if (s[2] == ')') {
  48.           if (s[3] == 'A') {
  49.             state2 = STATE2_DESIGNATED_GB2312;
  50.             s += 4; count += 4;
  51.             if (n < count+1)
  52.               goto none;
  53.             continue;
  54.           }
  55.           if (s[3] == 'G') {
  56.             state2 = STATE2_DESIGNATED_CNS11643_1;
  57.             s += 4; count += 4;
  58.             if (n < count+1)
  59.               goto none;
  60.             continue;
  61.           }
  62.         }
  63.         if (s[2] == '*') {
  64.           if (s[3] == 'H') {
  65.             state3 = STATE3_DESIGNATED_CNS11643_2;
  66.             s += 4; count += 4;
  67.             if (n < count+1)
  68.               goto none;
  69.             continue;
  70.           }
  71.         }
  72.       }
  73.       if (s[1] == 'N') {
  74.         switch (state3) {
  75.           case STATE3_NONE:
  76.             return RET_ILSEQ;
  77.           case STATE3_DESIGNATED_CNS11643_2:
  78.             if (s[2] < 0x80 && s[3] < 0x80) {
  79.               int ret = cns11643_2_mbtowc(conv,pwc,s+2,2);
  80.               if (ret == RET_ILSEQ)
  81.                 return RET_ILSEQ;
  82.               if (ret != 2) abort();
  83.               COMBINE_STATE;
  84.               conv->istate = state;
  85.               return count+4;
  86.             } else
  87.               return RET_ILSEQ;
  88.           default: abort();
  89.         }
  90.       }
  91.       return RET_ILSEQ;
  92.     }
  93.     if (c == SO) {
  94.       if (state2 != STATE2_DESIGNATED_GB2312 && state2 != STATE2_DESIGNATED_CNS11643_1)
  95.         return RET_ILSEQ;
  96.       state1 = STATE_TWOBYTE;
  97.       s++; count++;
  98.       if (n < count+1)
  99.         goto none;
  100.       continue;
  101.     }
  102.     if (c == SI) {
  103.       state1 = STATE_ASCII;
  104.       s++; count++;
  105.       if (n < count+1)
  106.         goto none;
  107.       continue;
  108.     }
  109.     break;
  110.   }
  111.   switch (state1) {
  112.     case STATE_ASCII:
  113.       if (c < 0x80) {
  114.         int ret = ascii_mbtowc(conv,pwc,s,1);
  115.         if (ret == RET_ILSEQ)
  116.           return RET_ILSEQ;
  117.         if (ret != 1) abort();
  118.         if (*pwc == 0x000a || *pwc == 0x000d) {
  119.           state2 = STATE2_NONE; state3 = STATE3_NONE;
  120.         }
  121.         COMBINE_STATE;
  122.         conv->istate = state;
  123.         return count+1;
  124.       } else
  125.         return RET_ILSEQ;
  126.     case STATE_TWOBYTE:
  127.       if (n < count+2)
  128.         goto none;
  129.       if (s[0] < 0x80 && s[1] < 0x80) {
  130.         int ret;
  131.         switch (state2) {
  132.           case STATE2_NONE:
  133.             return RET_ILSEQ;
  134.           case STATE2_DESIGNATED_GB2312:
  135.             ret = gb2312_mbtowc(conv,pwc,s,2); break;
  136.           case STATE2_DESIGNATED_CNS11643_1:
  137.             ret = cns11643_1_mbtowc(conv,pwc,s,2); break;
  138.           default: abort();
  139.         }
  140.         if (ret == RET_ILSEQ)
  141.           return RET_ILSEQ;
  142.         if (ret != 2) abort();
  143.         COMBINE_STATE;
  144.         conv->istate = state;
  145.         return count+2;
  146.       } else
  147.         return RET_ILSEQ;
  148.     default: abort();
  149.   }
  150.  
  151. none:
  152.   COMBINE_STATE;
  153.   conv->istate = state;
  154.   return RET_TOOFEW(count);
  155. }
  156.  
  157. static int
  158. iso2022_cn_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)
  159. {
  160.   state_t state = conv->ostate;
  161.   SPLIT_STATE;
  162.   unsigned char buf[3];
  163.   int ret;
  164.  
  165.   /* Try ASCII. */
  166.   ret = ascii_wctomb(conv,buf,wc,1);
  167.   if (ret != RET_ILSEQ) {
  168.     if (ret != 1) abort();
  169.     if (buf[0] < 0x80) {
  170.       int count = (state1 == STATE_ASCII ? 1 : 2);
  171.       if (n < count)
  172.         return RET_TOOSMALL;
  173.       if (state1 != STATE_ASCII) {
  174.         r[0] = SI;
  175.         r += 1;
  176.         state1 = STATE_ASCII;
  177.       }
  178.       r[0] = buf[0];
  179.       if (wc == 0x000a || wc == 0x000d) {
  180.         state2 = STATE2_NONE; state3 = STATE3_NONE;
  181.       }
  182.       COMBINE_STATE;
  183.       conv->ostate = state;
  184.       return count;
  185.     }
  186.   }
  187.  
  188.   /* Try GB 2312-1980. */
  189.   ret = gb2312_wctomb(conv,buf,wc,2);
  190.   if (ret != RET_ILSEQ) {
  191.     if (ret != 2) abort();
  192.     if (buf[0] < 0x80 && buf[1] < 0x80) {
  193.       int count = (state2 == STATE2_DESIGNATED_GB2312 ? 0 : 4) + (state1 == STATE_TWOBYTE ? 0 : 1) + 2;
  194.       if (n < count)
  195.         return RET_TOOSMALL;
  196.       if (state2 != STATE2_DESIGNATED_GB2312) {
  197.         r[0] = ESC;
  198.         r[1] = '$';
  199.         r[2] = ')';
  200.         r[3] = 'A';
  201.         r += 4;
  202.         state2 = STATE2_DESIGNATED_GB2312;
  203.       }
  204.       if (state1 != STATE_TWOBYTE) {
  205.         r[0] = SO;
  206.         r += 1;
  207.         state1 = STATE_TWOBYTE;
  208.       }
  209.       r[0] = buf[0];
  210.       r[1] = buf[1];
  211.       COMBINE_STATE;
  212.       conv->ostate = state;
  213.       return count;
  214.     }
  215.   }
  216.  
  217.   ret = cns11643_wctomb(conv,buf,wc,3);
  218.   if (ret != RET_ILSEQ) {
  219.     if (ret != 3) abort();
  220.  
  221.     /* Try CNS 11643-1992 Plane 1. */
  222.     if (buf[0] == 0 && buf[1] < 0x80 && buf[2] < 0x80) {
  223.       int count = (state2 == STATE2_DESIGNATED_CNS11643_1 ? 0 : 4) + (state1 == STATE_TWOBYTE ? 0 : 1) + 2;
  224.       if (n < count)
  225.         return RET_TOOSMALL;
  226.       if (state2 != STATE2_DESIGNATED_CNS11643_1) {
  227.         r[0] = ESC;
  228.         r[1] = '$';
  229.         r[2] = ')';
  230.         r[3] = 'G';
  231.         r += 4;
  232.         state2 = STATE2_DESIGNATED_CNS11643_1;
  233.       }
  234.       if (state1 != STATE_TWOBYTE) {
  235.         r[0] = SO;
  236.         r += 1;
  237.         state1 = STATE_TWOBYTE;
  238.       }
  239.       r[0] = buf[1];
  240.       r[1] = buf[2];
  241.       COMBINE_STATE;
  242.       conv->ostate = state;
  243.       return count;
  244.     }
  245.  
  246.     /* Try CNS 11643-1992 Plane 2. */
  247.     if (buf[0] == 1 && buf[1] < 0x80 && buf[2] < 0x80) {
  248.       int count = (state3 == STATE3_DESIGNATED_CNS11643_2 ? 0 : 4) + 4;
  249.       if (n < count)
  250.         return RET_TOOSMALL;
  251.       if (state3 != STATE3_DESIGNATED_CNS11643_2) {
  252.         r[0] = ESC;
  253.         r[1] = '$';
  254.         r[2] = '*';
  255.         r[3] = 'H';
  256.         r += 4;
  257.         state3 = STATE3_DESIGNATED_CNS11643_2;
  258.       }
  259.       r[0] = ESC;
  260.       r[1] = 'N';
  261.       r[2] = buf[1];
  262.       r[3] = buf[2];
  263.       COMBINE_STATE;
  264.       conv->ostate = state;
  265.       return count;
  266.     }
  267.   }
  268.  
  269.   return RET_ILSEQ;
  270. }
  271.  
  272. static int
  273. iso2022_cn_reset (conv_t conv, unsigned char *r, int n)
  274. {
  275.   state_t state = conv->ostate;
  276.   SPLIT_STATE;
  277.   (void)state2;
  278.   (void)state3;
  279.   if (state1 != STATE_ASCII) {
  280.     if (n < 1)
  281.       return RET_TOOSMALL;
  282.     r[0] = SI;
  283.     /* conv->ostate = 0; will be done by the caller */
  284.     return 1;
  285.   } else
  286.     return 0;
  287. }
  288.  
  289. #undef COMBINE_STATE
  290. #undef SPLIT_STATE
  291. #undef STATE3_DESIGNATED_CNS11643_2
  292. #undef STATE3_NONE
  293. #undef STATE2_DESIGNATED_CNS11643_1
  294. #undef STATE2_DESIGNATED_GB2312
  295. #undef STATE2_NONE
  296. #undef STATE_TWOBYTE
  297. #undef STATE_ASCII
  298.